#! /usr/bin/env python
# -*- coding: utf8 -*-

# Alexandre Coster <acoster@rhrk.uni-kl.de>
# AG DBIS - Technische Universität Kaiserslautern

"""
This module holds the L{probDistr} class, which is an abstraction for pseudo-random number generators.
"""

import sys
import random

if __name__ == "__main__":
    print "You shouldn't be running this file!"
    sys.exit()

class probDistr:
    """
    This class represents a probability distribution. Each instance is an callable object that returns a pseudo-random number, using 
    parameters (such as which function will it use to generate the numbers, and its parameters) provided to the constructor. The functions
    used to generate the numbers are the ones provided on the U{C{random} <http://docs.python.org/lib/module-random.html>} module.
    """

    def __init__(self, distrNode):
        """
        Constructor for the C{probDistr} class. Receives an XML node containing the configuration for it, as described on the xXML manual,
        a.k.a. my report. The C{<base>} node's text contains the function name that will be used as base, that is, C{random.<<base>'s text>}
        will be used as random number generator, with the parameters configured inside the C{<parameters>} node, as also explained on the 
        manual.

        @param distrNode: ElementTree node for the XML root (C{<distribution>}) of the distribution's configuration
        @type distrNode: Element
        """
        self.__parameters = {}

        self.__distr = distrNode.find("base").text.strip()

        # here lays the reflection
        self.__func = getattr(random, self.__distr)

        # random.randint() doesn't accept float arguments
        if self.__distr == "randint":
            for i in distrNode.findall("./parameters/*"):
                self.__parameters[i.tag] = int(i.text.strip())
        else:
            for i in distrNode.findall("./parameters/*"):
                self.__parameters[i.tag] = float(i.text.strip())

    # makes an object of this class callable
    def __call__(self):
        """
        Returns a random number, obtained using the configured function, with the defined arguments.

        @return: A random number (either a float or an integer).
        """

        # the ** means to expand the dictionary into a named parameter list.
        return self.__func(**self.__parameters)
